package model

import (
	"errors"
	"fmt"
	"math/rand"
	"strconv"
	"time"

	"bmember/pkg/util"
)

const (
	RechargeOrderUnpayed       int8 = 1 // 未支付
	RechargeOrderPaying        int8 = 2 // 支付中
	RechargeOrderPayed         int8 = 3 // 已经付款
	RechargeOrderRefundApplied int8 = 4 // 申请退款
	RechargeOrderRefunding     int8 = 5 // 退款中
	RechargeOrderRefunded      int8 = 6 // 退款完成
	RechargeOrderPayFailed     int8 = 7 // 支付失败
	RechargeOrderRefundFailed  int8 = 8 // 退款失败

	RechargeOrderClosed int8 = 99 // 订单关闭

	RechargeOrderUnpayedStr       = "unpayed"        // 未支付
	RechargeOrderPayingStr        = "paying"         // 支付中
	RechargeOrderPayedStr         = "payed"          // 已经付款
	RechargeOrderRefundAppliedStr = "refund_applied" // 申请退款
	RechargeOrderRefundingStr     = "refunding"      // 退款中
	RechargeOrderRefundedStr      = "refunded"       // 退款完成
	RechargeOrderPayFailedStr     = "pay_failed"     // 支付失败
	RechargeOrderRefundFailedStr  = "refund_failed"  // 退款失败

	RechargeOrderClosedStr = "closed" // 订单关闭

	// 数值时间
	NumberLayout = "20060102150405"
)

var payStatus = []int8{1, 2, 3, 7}
var refundStatus = []int8{4, 5, 6, 8}

// RechargeOrderRemark 余额日志备注
type RechargeOrderRemark struct {
	Reason string `json:"reason"`
}

// RechargeOrder 充值订单
type RechargeOrder struct {
	Id int64 `json:"id" sql:"id"`
	// 品牌id
	BrandId int64 `json:"brand_id" sql:"brand_id"`
	// 门店id 0~品牌
	StoreId int64 `json:"store_id" sql:"store_id"`
	// 体系id
	GroupId int64 `json:"group_id" sql:"group_id"`
	// 卡id
	CardId int64 `json:"card_id" sql:"card_id"`
	// 会员id
	MemberId int64 `json:"member_id" sql:"member_id"`
	// 账号id
	AccId int64 `json:"acc_id" sql:"acc_id"`
	// 订单号
	OrderNo string `json:"order_no" sql:"order_no"`
	// 订单金额
	Amount uint64 `json:"amount" sql:"amount"`
	// 退款金额
	RefundAmount uint64 `json:"refund_amount" sql:"refund_amount"`
	// 用户支付金额
	Payed uint64 `json:"payed" sql:"payed"`
	// 支付系统退款金额
	Refunded uint64 `json:"refunded" sql:"refunded"`
	// 支付单单号
	PayOrderNo string `json:"pay_order_no" sql:"pay_order_no"`
	// 退款单单号 （暂时一个支付单只支持一次退款)
	RefundOrderNo string `json:"refund_order_no" sql:"refund_order_no"`
	// 支付时间
	PayedTime time.Time `json:"payed_time" sql:"payed_time"`
	// 退款时间
	RefundedTime time.Time `json:"refunded_time" sql:"refunded_time"`
	// 订单状态 1~未付款 2~付款中 3~已付款，4~申请退款 5~退款中 6~已退款 7~支付失败 8~退款失败 99~关闭订单
	Status int8 `json:"status" sql:"status"`
	// 订单来源, 同登陆渠道
	OrderSource string `json:"order_source" sql:"order_source"`
	// 营销大字段
	MarketingInfo []byte `json:"marketing_info" sql:"marketing_info"`
	// 备注大字段
	Remark    []byte    `json:"remark" sql:"remark"`
	CreatedAt time.Time `json:"created_at" sql:"created_at"`
	UpdatedAt time.Time `json:"updated_at" sql:"updated_at"`
	DeletedAt int64     `json:"deleted_at" sql:"deleted_at"`
}

// GenerateOrderNumber 单号生成器
func GenerateOrderNumber(now time.Time, orderType int8, memberId int64) (orderNumber string, err error) {
	orderKey := strconv.FormatInt(memberId, 10)
	if len(orderKey) > 10 {
		return "", errors.New("invalid_member_id")
	}
	orderKey = fmt.Sprintf("%0*d%s", 10-len(orderKey), 0, orderKey)
	randSource := rand.New(rand.NewSource(now.UnixNano()))
	orderNumber = fmt.Sprintf("%s%02d%s%02d", now.Format(NumberLayout), orderType, orderKey, randSource.Intn(100))
	return
}

// NewRechargeOrder 新建充值订单
func NewRechargeOrder(brandId, storeId, groupId, cardId, memberId, accId int64, amount uint64, source string) *RechargeOrder {
	now := util.GetNow()
	// 会员充值单的订单类型, 2 写死
	orderNo, _ := GenerateOrderNumber(now, 2, memberId)
	return &RechargeOrder{
		BrandId:       brandId,
		StoreId:       storeId,
		GroupId:       groupId,
		CardId:        cardId,
		MemberId:      memberId,
		AccId:         accId,
		OrderNo:       orderNo,
		Amount:        amount,
		Status:        RechargeOrderUnpayed,
		OrderSource:   source,
		MarketingInfo: []byte("{}"),
		Remark:        []byte("{}"),
		CreatedAt:     now,
		UpdatedAt:     now,
	}
}

// GetRemark 获取备注信息
func (r *RechargeOrder) GetRemark() *RechargeOrderRemark {
	ret := &RechargeOrderRemark{}
	if r.Remark != nil {
		_ = json.Unmarshal(r.Remark, ret)
	}
	return ret
}

// SetRemark 设置备注
func (r *RechargeOrder) SetRemark(remark *RechargeOrderRemark) {
	if remark != nil {
		r.Remark, _ = json.Marshal(remark)
		r.UpdatedAt = util.GetNow()
	}
}

// SetReason 设置原因
func (r *RechargeOrder) SetReason(reason string) {
	if reason != "" {
		remark := r.GetRemark()
		remark.Reason = reason
		r.SetRemark(remark)
	}
}

// PayOrderCreated 创建完支付单
func (r *RechargeOrder) PayOrderCreated(payOrderNo string) {
	r.PayOrderNo = payOrderNo
	r.Status = RechargeOrderPaying
	r.UpdatedAt = util.GetNow()
}

// HasPayed 已经付款
func (r *RechargeOrder) HasPayed(payAmount uint64) {
	now := util.GetNow()
	r.Payed = payAmount
	r.Status = RechargeOrderPayed
	r.PayedTime = now
	r.UpdatedAt = now
}

// UpdatePayStatus 更新支付状态
func (r *RechargeOrder) UpdatePayStatus(status int8, payed uint64, payOrderNo string, payTime time.Time) error {
	if !util.ContainInt8(payStatus, status) {
		return InvalidEnum
	}
	if r.Status == status {
		return nil
	}
	r.Status = status
	r.PayOrderNo = payOrderNo
	r.PayedTime = payTime
	r.Payed = payed
	r.UpdatedAt = util.GetNow()
	return nil
}

// IsPayed 是否已完成充值
func (r *RechargeOrder) IsPayed() bool {
	return r.Status == RechargeOrderPayed
}

// ApplyRefund 申请退款
func (r *RechargeOrder) ApplyRefund(refundAmount uint64, reason string) {
	r.Status = RechargeOrderRefundApplied
	r.RefundAmount = refundAmount
	r.SetReason(reason)
	r.UpdatedAt = util.GetNow()
}

// RefundOrderCreated 发起退款
func (r *RechargeOrder) RefundOrderCreated(refundOrderNo string) {
	r.RefundOrderNo = refundOrderNo
	r.Status = RechargeOrderRefunding
	r.UpdatedAt = util.GetNow()
}

// HasRefunded 退款成功
func (r *RechargeOrder) HasRefunded(refundAmount uint64) {
	now := util.GetNow()
	r.Status = RechargeOrderRefunded
	r.Refunded = refundAmount
	r.RefundedTime = now
	r.UpdatedAt = now
}

// IsRefunded 是否已经完成退款
func (r *RechargeOrder) IsRefunded() bool {
	return r.Status == RechargeOrderRefunded
}

// Delete 删除订单
func (r *RechargeOrder) Delete() error {
	if r.Status != RechargeOrderUnpayed {
		return InvalidStatus
	}
	r.DeletedAt = util.GetCurrentTimestamp()
	return nil
}

// IsFinished 是否已经完结
func (r *RechargeOrder) IsFinished() bool {
	switch r.Status {
	case RechargeOrderPayed, RechargeOrderRefunded, RechargeOrderPayFailed, RechargeOrderRefundFailed:
		return true
	default:
		return false
	}
}

// CanBePayed 是否可以支付
func (r *RechargeOrder) CanBePayed() bool {
	if r.Status == RechargeOrderUnpayed || r.Status == RechargeOrderRefunding {
		return true
	}
	return false
}

// GetStatus 获取状态
func (r *RechargeOrder) GetStatus() string {
	switch r.Status {
	case RechargeOrderUnpayed:
		return RechargeOrderUnpayedStr
	case RechargeOrderPaying:
		return RechargeOrderPayingStr
	case RechargeOrderPayed:
		return RechargeOrderPayedStr
	case RechargeOrderRefundApplied:
		return RechargeOrderRefundAppliedStr
	case RechargeOrderRefunding:
		return RechargeOrderRefundingStr
	case RechargeOrderRefunded:
		return RechargeOrderRefundedStr
	case RechargeOrderClosed:
		return RechargeOrderClosedStr
	case RechargeOrderPayFailed:
		return RechargeOrderPayFailedStr
	case RechargeOrderRefundFailed:
		return RechargeOrderRefundFailedStr
	default:
		return ""
	}
}
